@file:JvmMultifileClass
@file:JvmName("ContextKsl")

package hos.ksl

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.ContextWrapper
import android.content.res.ColorStateList
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Point
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.annotation.ArrayRes
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import hos.thread.CoroutineLayoutInflater
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

/**
 * <p>Title: ContextKSL </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-05-09 17:52
 * @version : 1.0
 */

fun Context?.findActivity(): Activity? {
    if (this == null) {
        return null
    }
    if (this is Activity) return this
    else if (this is ContextWrapper) {
        return this.baseContext?.findActivity()
    }
    return null
}

fun Context?.isActivityDestroyed(): Boolean {
    val activity = findActivity()
    if (activity != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return activity.isDestroyed || activity.isFinishing
        }
        return activity.isFinishing
    }
    return true
}

fun Context.width(): Int {
    val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager?
        ?: return -1
    return wm.width()
}

fun Context.height(): Int {
    val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager?
        ?: return -1
    return wm.height()
}

fun Window.width(): Int {
    return windowManager.width()
}

fun Window.height(): Int {
    return windowManager.height()
}

fun Dialog.width(): Int {
    return window?.width() ?: 0
}

fun Dialog.height(): Int {
    return window?.height() ?: 0
}

@Suppress("DEPRECATION")
fun WindowManager.width(): Int {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        return currentWindowMetrics.bounds.width()
    }
    val point = Point()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        defaultDisplay.getRealSize(point)
    } else {
        defaultDisplay.getSize(point)
    }
    return point.x
}
@Suppress("DEPRECATION")
fun WindowManager.height(): Int {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        return currentWindowMetrics.bounds.height()
    }
    val point = Point()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        defaultDisplay.getRealSize(point)
    } else {
        defaultDisplay.getSize(point)
    }
    return point.y
}


@JvmOverloads
suspend inline fun Context.inflate(
    @LayoutRes resId: Int, parent: ViewGroup? = null,
    dispatcher: CoroutineDispatcher = Dispatchers.Default
) = CoroutineLayoutInflater(this, dispatcher).inflate(resId, parent)


@JvmOverloads
fun LifecycleOwner.inflateScope(
    @LayoutRes resId: Int, parent: ViewGroup? = null,
    dispatcher: CoroutineDispatcher = Dispatchers.Default,
    content: View.() -> Unit
) = lifecycleScope.launch {
    val view = (this as Context).inflate(resId, parent, dispatcher)
    content(view)
}

fun Context.isTablet(): Boolean {
    return (resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >=
            Configuration.SCREENLAYOUT_SIZE_LARGE
}

fun Context.resString(@StringRes id: Int, vararg formatArgs: Any): String {
    return if (Build.VERSION.SDK_INT >= 23) {
        if (formatArgs.isEmpty()) {
            return getString(id)
        }
        getString(id, formatArgs)
    } else {
        if (formatArgs.isEmpty()) {
            return resources.getString(id)
        }
        resources.getString(id, formatArgs)
    }
}

fun Context.resTextArray(@ArrayRes id: Int): Array<out CharSequence> {
    return resources.getTextArray(id)
}

fun Context.resStringArray(@ArrayRes id: Int): Array<out CharSequence> {
    return resources.getStringArray(id)
}

fun Context.resIntArray(@ArrayRes id: Int): IntArray {
    return resources.getIntArray(id)
}

fun Context.resMipmapArray(@ArrayRes id: Int): IntArray {
    val typedArray = resources.obtainTypedArray(id)
    try {
        val len: Int = typedArray.length()
        val oaIcon = IntArray(len)
        for (i in 0 until len) {
            oaIcon[i] = typedArray.getResourceId(i, 0)
        }
        return oaIcon
    } finally {
        typedArray.recycle()
    }
}

fun Context.resDrawable(@DrawableRes id: Int): Drawable? {
    return ContextCompat.getDrawable(this, id)
}

fun Context.resColor(@ColorRes id: Int): Int {
    return if (Build.VERSION.SDK_INT >= 23) {
        getColor(id)
    } else {
        ContextCompat.getColor(this,id)
    }
}

@SuppressLint("UseCompatLoadingForColorStateLists")
fun Context.resColorStateList(@ColorRes id: Int): ColorStateList {
    return if (Build.VERSION.SDK_INT >= 23) {
        getColorStateList(id)
    } else {
        @Suppress("DEPRECATION")
        resources.getColorStateList(id)
    }
}

/**
 * Return the navigation bar's height.
 *
 * @return the navigation bar's height
 */
@SuppressLint("DiscouragedApi", "InternalInsetResource")
fun Context.getNavBarHeight(): Int {
    val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
    return if (resourceId != 0) {
        resources.getDimensionPixelSize(resourceId)
    } else {
        0
    }
}

/**
 * Return the status bar's height.
 *
 * @return the status bar's height
 */
@SuppressLint("DiscouragedApi", "InternalInsetResource")
fun Context.getStatusBarHeight(): Int {
    val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
    if (resourceId == 0) {
        return 0
    }
    return resources.getDimensionPixelSize(resourceId)
}